﻿using STHPMS1.Common.C_Entity;
using STHPMS1.Common.C_Entity.Stmpms1;
using STHPMS1.Common.C_Enum;
using STHPMS1.ICore;
using STHPMS1.ICore.I_Core;
using STHPMS1.ICore.I_UI;
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using STHPMS1.Common.C_Extension;
using STHPMS1.ICore.I_Serv;
using System.Data;
using System.IO;
using System.Reflection;
using System.Collections.Generic;
using System.Linq.Expressions;


namespace STHPMS1.Web.W_Controller
{
    [RoutePrefix("api/sturcture")]
    public class B_SturcturePage1Controller : STHPMS1.Web.W_Core.MyController
    {
        [Route("")]
        [Route("page/{page?}", Name = "GetsturctureByPage")]
        [Route("rows/{rows?}")]
        [Route("page/{page?}/rows/{rows?}")]
        public IHttpActionResult Get(string road = null, int page = 1,  int rows = 10)
        {
            int p = page;
            int s = rows;

            PagingInfo info = new PagingInfo();
            info.PageIndex = p> 0 ? p - 1 : 0;
            info.PageSize = s;
            info.TotalRecords = 0;

            Expression<Func<B_Sturcture, bool>> exp = null;
            if (road != null && road.ToString().Length > 0)
                exp = pre => pre.Rdwayid == road.ToString();


            var data = this.Scene.Bll.B_Sturcture.Get<B_Sturcture>(exp, info).ToArray();
            if(data==null) return NotFound();

            var result = new { rows = data, total = info.TotalRecords };

            return Ok(result);
        }

        [Route("")]
        public HttpResponseMessage Post(B_Sturcture entity)
        {
            this.Scene.Bll.B_Sturcture.Save(entity);

            var response = Request.CreateResponse(HttpStatusCode.Created);
            string uri = Url.Link("GetsturctureByPage", new { page = 1 });
            response.Headers.Location = new Uri(uri);

            return response;
        }

        [Route("")]
        public void Delete(B_Sturcture entity)
        {
            this.Scene.Bll.B_Sturcture.Remove(entity);
        }

        #region 构造物桩号重叠校验
        private void CheckSturctureData(DataTable b_pmstc)
        {
            List<string> keys = new List<string>();
            //提取路线编号和行车方向进行分组
            foreach (DataRow drKeys in b_pmstc.Rows)
            {
                string rdid = drKeys["RDWAYID"].ToString();//路线编号
                string dir = drKeys["DIRECTION_DICTID"].ToString();//行车方向

                if (!keys.Contains(rdid + "_" + dir))
                    keys.Add(rdid + "_" + dir);
            }
            foreach (string key in keys)
            {
                string[] temp = key.Split('_');

                DataRow[] drs = b_pmstc.Select("rdwayid='" + temp[0] + "' and DIRECTION_DICTID=" + temp[1], "beginmp"); //筛选路线编号和行车方向相同的数据

                //检查重叠
                CheckOverlap(drs, temp[0]);
            }
        }

        private void CheckOverlap(DataRow[] drs, string rdid)
        {
            List<B_Roadway> lst = null;
            if (!Common.C_Utils.MyCacheTools.IsCacheExist(rdid))
            {
                //查询路线编号的起点和终点桩号
                lst = this.Scene.Bll.B_Roadway.SearchById<B_Roadway>(rdid);
                Common.C_Utils.MyCacheTools.SetCache(rdid, lst, 24);
            }
            else
            {
                lst = Common.C_Utils.MyCacheTools.GetCache(rdid) as List<B_Roadway>;
            }

            if (lst.Count == 0) throw new Exception("路线编号" + rdid + "不存在");
            //drs排序
            List<DataRow> lstSort = new List<DataRow>();
            foreach (DataRow d in drs)
                lstSort.Add(d);
            lstSort.Sort(new ArticleCompare());
            drs = lstSort.ToArray();

            //起终检查 
            if (Convert.ToDouble(drs[0]["BEGINMP"]) < lst[0].Beginmp || Convert.ToDouble(drs[drs.Length - 1]["ENDMP"]) > lst[0].Endmp)
            {
                string msg = string.Format("Excel中起终点桩号超出路线编号{0}的起终点桩号:EXCEL桩号[{3}-{4}]，实际桩号[{1}-{2}]", rdid, lst[0].Beginmp, lst[0].Endmp, Convert.ToDouble(drs[0]["BEGINMP"]), Convert.ToDouble(drs[drs.Length - 1]["ENDMP"]));
                throw new Exception(msg);
            }
            //两行以上的桩号首尾空白检查
            if (drs.Length > 1)
            {
                int j = 1;
                for (int i = 0; i < drs.Length - 1; i++)
                {
                    if (Convert.ToDouble(drs[j]["BEGINMP"])<Convert.ToDouble(drs[i]["ENDMP"]))
                    {
                        throw new Exception("Excel中路线编号" + rdid + "的构造物桩号存在重叠");
                    }
                    j++;
                }
            }
        }
        #endregion

        /// <summary>
        /// 上传数据处理
        /// </summary>
        /// <param name="file">文件路径</param>
        /// <param name="rdid">路线编号</param>
        /// <returns></returns>
        [Route("saveFile")]
        public HttpResponseMessage PostSaveFile(string file)
        {
            DataTable entity = null;//实体数据
            Excel_BaseImportData exData = null;//导入数据
            if (File.Exists(file))
            {
                try
                {
                    int startRow = 0;//Excel列头位置
                    List<string> keys = new List<string>();//路线编号
                    DataTable dt = Common.C_Excel.ExcelTool.RenderDataTableFromExcel(file, startRow);//获取Excel的DataTable
                    //验证Excel表头格式?
                    entity = GetData(dt, startRow, keys);//将要导入的实体Table
                    //校验构造物桩号不能重叠
                    CheckSturctureData(entity);

                    exData = new Excel_BaseImportData(new B_Sturcture());//构造物实体
                    exData.DtSource = entity;
                    exData.TableName = "B_Sturcture"; //构造物 
                    this.Scene.Bll.Excel.ImportData(exData);
                    Common.C_Utils.MyCacheTools.ClearAllCache();//清空缓存
                }
                catch (Exception ex)
                {
                    File.Delete(file);//删除上传数据
                    //抛出错误
                    var response = new HttpResponseMessage(HttpStatusCode.InternalServerError)
                    {
                        Content = new StringContent(ex.Message),
                        ReasonPhrase = "Server Error"
                    };
                    throw new HttpResponseException(response);
                }
                finally
                {
                    Common.C_Utils.MyCacheTools.ClearAllCache();
                }
            }
            else
            {
                //抛出错误
                var response = new HttpResponseMessage(HttpStatusCode.InternalServerError)
                {
                    Content = new StringContent("服务器未能保存上传文件，请联系管理员"),
                    ReasonPhrase = "Server Error"
                };
                throw new HttpResponseException(response);
            }
            var res = Request.CreateResponse(HttpStatusCode.Created);
            string uri = Url.Link("GetsturctureByPage", new { page = 1 });
            res.Headers.Location = new Uri(uri);

            return res;
         
        }

        /// <summary>
        /// 反射获取对象的所有属性
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        private PropertyInfo[] GetAllProperty(object t)
        {
            Type temp = t.GetType();
            return temp.GetProperties();
        }
        /// <summary>
        /// 获取交通量的实体
        /// </summary>
        /// <param name="excel">导入的Excel</param>
        /// <param name="Rdwayid">路线编号</param>
        ///<param name="startRow">提取位置</param>
        /// <returns></returns>
        private DataTable GetData(DataTable excel, int startRow, List<string> keys)
        {
            //检测输入的起点，结束桩号是否在该路线中          

            DataTable kh = new DataTable();
            PropertyInfo[] propertys = GetAllProperty(new B_Sturcture());
            foreach (PropertyInfo p in propertys)
            {
                kh.Columns.Add(new DataColumn(p.Name.ToUpper()));
            }
            kh.Columns.Add(new DataColumn("index")); //记录错误行号
            if (excel.Rows.Count == 0)
            {
                throw new Exception("Excel没有数据");
            }
            string _IMPORTDATE = DateTime.Now.ToShortDateString();//导入时间
            int index = startRow + 1;
            foreach (DataRow r in excel.Rows)
            { 
                string _RDWAYID = r[0].ToString();//路线编号
                string _STRUNAME = r[1].ToString();//构造物名称    
                int _STTYPE_DICTID = GetSturctureEnum(r[2].ToString());//结构类型(匹配字典表)
                if (_STTYPE_DICTID == -1)
                {
                    throw new Exception("第"+index+"行的结构类型与系统定义不匹配");
                }           
                double _BEGINMP = Convert.ToDouble( r[3]);//起点桩号
                double _ENDMP = Convert.ToDouble(r[4]);//终点桩号
                double  version = this.Scene.Bll.B_Roadway.GetNewHistoryVersion(_RDWAYID);//版本号
                //检测输入的起点，结束桩号是否在该路线中 
                B_Roadway roads = GetRoad(_RDWAYID);
                if (roads == null)
                {
                    throw new Exception("未能找到路线编号" + _RDWAYID);
                }
                else
                {
                    if (_BEGINMP < roads.Beginmp || _ENDMP > roads.Endmp)
                    {
                        string msg = string.Format("路线{4}的起终点桩号超出实际桩号:Excel桩号[{0}-{1}],实际路线桩号[{2}-{3}]", _BEGINMP, _ENDMP, roads.Beginmp, roads.Endmp, _RDWAYID);
                        throw new Exception(msg);
                    }
                }
                //存放不同的编号
                if(!keys.Contains(_RDWAYID))
                {
                    keys.Add(_RDWAYID);
                }
                string dir = r[5].ToString();//方向
                int _STFUCLASS_DICTID = GetSTFUCLASS(_STTYPE_DICTID,r[6].ToString());//功能分类(匹配字典表)
                if (_STFUCLASS_DICTID == -1)
                {
                    throw new Exception("第" + index + "行的功能类型与系统定义不匹配");
                }
                double _LENGTH = _ENDMP-_BEGINMP;//结构长度
                if(_LENGTH<=0)
                {
                    throw new Exception("第" + index + "行的构造物长度不符合要求");
                }
                int _TECHCLASS_DICTID = GetTECHCLASS(_STTYPE_DICTID, _LENGTH);//技术等级(匹配字典表) -1 表示为涵洞
                string _STRUWID = r[7].ToString();//构造物宽度
                string _BEGINDATE = r[8].ToString();//通车时间          

                //创建一个构造物类型，得到ID
               
                if(dir=="全幅")
                {
                    B_Sturcture b = new B_Sturcture()
                    {
                        Sttype_Dictid = _STTYPE_DICTID,
                        Rdwayid = _RDWAYID,
                        Beginmp = _BEGINMP,
                        Direction_Dictid = (int)Common.C_Enum.DirectionEnum.All13
                    };
                    STHPMS1.BLL.B_Serv.IdGenrateService idService = new BLL.B_Serv.IdGenrateService();
                    string _STRUID = idService.NewSturctureId(b);//ID生成规则: QL_路线编号_起点桩号(SD,HD)_方向
                    DataRow dr = kh.NewRow();
                    dr["STRUID"] = _STRUID;
                    dr["RDWAYID"] = _RDWAYID;
                    dr["STRUNAME"] = _STRUNAME;
                    dr["STTYPE_DICTID"] = _STTYPE_DICTID;
                    dr["BEGINMP"] = _BEGINMP;
                    dr["ENDMP"] = _ENDMP;
                    dr["STFUCLASS_DICTID"] = _STFUCLASS_DICTID;
                    dr["LENGTH"] = _LENGTH;
                    if (_TECHCLASS_DICTID != -1)
                        dr["TECHCLASS_DICTID"] = _TECHCLASS_DICTID;
                    else 
                        dr["TECHCLASS_DICTID"] = DBNull.Value;
                    dr["STRUWID"] = _STRUWID;
                    dr["BEGINDATE"] = _BEGINDATE;
                    dr["IMPORTDATE"] = DateTime.Now.ToShortDateString();
                    dr["HIS_VERSION"] = version;
                    dr["DIRECTION_DICTID"] = b.Direction_Dictid;
                    dr["index"] = index++;
                    kh.Rows.Add(dr);
                }
                else
                {
                    //添加两行
                    B_Sturcture b = new B_Sturcture()
                    {
                        Sttype_Dictid = _STTYPE_DICTID,
                        Rdwayid = _RDWAYID,
                        Beginmp = _BEGINMP,
                        Direction_Dictid = (int)Common.C_Enum.DirectionEnum.Up11
                    };
                    STHPMS1.BLL.B_Serv.IdGenrateService idService = new BLL.B_Serv.IdGenrateService();
                    string _STRUID = idService.NewSturctureId(b);//ID生成规则: QL_路线编号_起点桩号(SD,HD)_方向
                    DataRow dr = kh.NewRow();
                    dr["STRUID"] = _STRUID;
                    dr["RDWAYID"] = _RDWAYID;
                    dr["STRUNAME"] = _STRUNAME;
                    dr["STTYPE_DICTID"] = _STTYPE_DICTID;
                    dr["BEGINMP"] = _BEGINMP;
                    dr["ENDMP"] = _ENDMP;
                    dr["STFUCLASS_DICTID"] = _STFUCLASS_DICTID;
                    dr["LENGTH"] = _LENGTH;
                    if (_TECHCLASS_DICTID != -1)
                        dr["TECHCLASS_DICTID"] = _TECHCLASS_DICTID;
                    else
                        dr["TECHCLASS_DICTID"] = DBNull.Value;
                    dr["STRUWID"] = _STRUWID;
                    dr["BEGINDATE"] = _BEGINDATE;
                    dr["IMPORTDATE"] = DateTime.Now.ToShortDateString();
                    dr["HIS_VERSION"] = version;
                    dr["DIRECTION_DICTID"] = b.Direction_Dictid;
                    dr["index"] = index++;
                    kh.Rows.Add(dr);

                    //第2行
                     b = new B_Sturcture()
                    {
                        Sttype_Dictid = _STTYPE_DICTID,
                        Rdwayid = _RDWAYID,
                        Beginmp = _BEGINMP,
                        Direction_Dictid = (int)Common.C_Enum.DirectionEnum.Down12
                    };
                    _STRUID = idService.NewSturctureId(b);//ID生成规则: QL_路线编号_起点桩号(SD,HD)_方向
                    dr = kh.NewRow();
                    dr["STRUID"] = _STRUID;
                    dr["RDWAYID"] = _RDWAYID;
                    dr["STRUNAME"] = _STRUNAME;
                    dr["STTYPE_DICTID"] = _STTYPE_DICTID;
                    dr["BEGINMP"] = _BEGINMP;
                    dr["ENDMP"] = _ENDMP;
                    dr["STFUCLASS_DICTID"] = _STFUCLASS_DICTID;
                    dr["LENGTH"] = _LENGTH;
                    if (_TECHCLASS_DICTID != -1)
                        dr["TECHCLASS_DICTID"] = _TECHCLASS_DICTID;
                    else
                        dr["TECHCLASS_DICTID"] = DBNull.Value;
                    dr["STRUWID"] = _STRUWID;
                    dr["BEGINDATE"] = _BEGINDATE;
                    dr["IMPORTDATE"] = DateTime.Now.ToShortDateString();
                    dr["HIS_VERSION"] = version;
                    dr["DIRECTION_DICTID"] = b.Direction_Dictid;
                    dr["index"] = index++;
                    kh.Rows.Add(dr);
                }
               

            }
            return kh;
        }


        #region 字典数据
        /// <summary>
        /// 返回功能分类
        /// </summary>
        /// <param name="temp"></param>
        /// <returns></returns>
        private int GetSTFUCLASS(int sturcture, string temp)
        {
            if(sturcture==(int)Common.C_Enum.SturctureEnum.B111) //桥梁
            {
                if (Common.C_Enum.BridgeEnum.B112.GetEnumDescription() == temp) //桥梁类型
                    return Common.C_Enum.BridgeEnum.B112.GetEnumValue();
                else if (Common.C_Enum.BridgeEnum.B113.GetEnumDescription() == temp) //桥梁类型
                    return Common.C_Enum.BridgeEnum.B113.GetEnumValue();
                else if (Common.C_Enum.BridgeEnum.B114.GetEnumDescription() == temp) //桥梁类型
                    return Common.C_Enum.BridgeEnum.B114.GetEnumValue();
                else if (Common.C_Enum.BridgeEnum.B115.GetEnumDescription() == temp) //桥梁类型
                    return Common.C_Enum.BridgeEnum.B115.GetEnumValue();
                else if (Common.C_Enum.BridgeEnum.B116.GetEnumDescription() == temp) //桥梁类型
                    return Common.C_Enum.BridgeEnum.B116.GetEnumValue();
                else if (Common.C_Enum.BridgeEnum.B117.GetEnumDescription() == temp) //桥梁类型
                    return Common.C_Enum.BridgeEnum.B117.GetEnumValue();
                else if (Common.C_Enum.BridgeEnum.B118.GetEnumDescription() == temp) //桥梁类型
                    return Common.C_Enum.BridgeEnum.B118.GetEnumValue();
                
            }
            else if (sturcture == (int)Common.C_Enum.SturctureEnum.C125) //隧道
            {
                if (Common.C_Enum.TunnelEnum.T121.GetEnumDescription() == temp) //隧道类型
                    return Common.C_Enum.TunnelEnum.T121.GetEnumValue();
                else if (Common.C_Enum.TunnelEnum.T122.GetEnumDescription() == temp) //隧道类型
                    return Common.C_Enum.TunnelEnum.T122.GetEnumValue();
                else if (Common.C_Enum.TunnelEnum.T123.GetEnumDescription() == temp) //隧道类型
                    return Common.C_Enum.TunnelEnum.T123.GetEnumValue();
            }
            else //涵洞
            {
                if (Common.C_Enum.CulvertEnum.C126.GetEnumDescription() == temp) //涵洞类型
                    return Common.C_Enum.CulvertEnum.C126.GetEnumValue();
                else if (Common.C_Enum.CulvertEnum.C127.GetEnumDescription() == temp) //涵洞类型
                    return Common.C_Enum.CulvertEnum.C127.GetEnumValue();
                else if (Common.C_Enum.CulvertEnum.C128.GetEnumDescription() == temp) //涵洞类型
                    return Common.C_Enum.CulvertEnum.C128.GetEnumValue();
                else if (Common.C_Enum.CulvertEnum.C129.GetEnumDescription() == temp) //涵洞类型
                    return Common.C_Enum.CulvertEnum.C129.GetEnumValue();
            }
            return -1;
        }

        /// <summary>
        /// 返回结构类型对应的枚举
        /// </summary>
        /// <param name="temp">用户输入</param>
        /// <returns></returns>
        private int GetSturctureEnum(string temp)
        {
            if (Common.C_Enum.SturctureEnum.B111.GetEnumDescription() == temp) //桥梁
                return Common.C_Enum.SturctureEnum.B111.GetEnumValue();
            else if (Common.C_Enum.SturctureEnum.C125.GetEnumDescription() == temp)//隧道
                return Common.C_Enum.SturctureEnum.C125.GetEnumValue();
            else if (Common.C_Enum.SturctureEnum.T120.GetEnumDescription() == temp)//涵洞
                return Common.C_Enum.SturctureEnum.T120.GetEnumValue();
            return -1;
        }

        /// <summary>
        /// 返回技术等级
        /// </summary>
        /// <param name="temp"></param>
        /// <returns></returns>
        private int GetTECHCLASS(int sturcture, double len)
        {
            if (sturcture == (int)Common.C_Enum.SturctureEnum.B111) //桥梁
            {
                if (len > 1000) return (int)Common.C_Enum.BridgeTechnicalEnum.B141;
                else if (len >= 100 && len <= 1000) return (int)Common.C_Enum.BridgeTechnicalEnum.B142;
                else if (len > 30 && len < 100) return (int)Common.C_Enum.BridgeTechnicalEnum.B143;
                else if (len >= 8 && len <= 30) return (int)Common.C_Enum.BridgeTechnicalEnum.B144;
                else throw new Exception("提供的桥梁长度有误，请检查起始桩号");
            }
            else if (sturcture == (int)Common.C_Enum.SturctureEnum.C125) //隧道
            {
                if (len > 3000) return (int)Common.C_Enum.TunnelTechnicalEnum.T146;
                else if (len > 1000 && len <= 3000) return (int)Common.C_Enum.TunnelTechnicalEnum.T147;
                else if (len > 500 && len <= 1000) return (int)Common.C_Enum.TunnelTechnicalEnum.T148;
                else return (int)Common.C_Enum.TunnelTechnicalEnum.T149;
            }

            return -1;
        }

        #endregion

        /// <summary>
        /// 上传返回上传后路径
        /// </summary>
        [Route("uploadFile")]
        public void PostUploadFile()
        {

            System.Web.HttpFileCollection hfc = System.Web.HttpContext.Current.Request.Files;
            string uploadPath =
              System.Web.HttpContext.Current.Server.MapPath("~/App_Data/Upload") + "\\";
            string PhysicalPath = "";
            if (hfc.Count > 0)
            {
                if (!Directory.Exists(uploadPath))
                {
                    Directory.CreateDirectory(uploadPath);
                }
                PhysicalPath = uploadPath + hfc[0].FileName;
                hfc[0].SaveAs(PhysicalPath);
            }

            System.Web.HttpContext.Current.Response.Write(PhysicalPath);
            System.Web.HttpContext.Current.Response.End();
        }

        /// <summary>
        /// 路线信息
        /// </summary>
        /// <param name="stru_id"></param>
        /// <returns></returns>
        public B_Roadway GetRoad(string rdid)
        {
            List<B_Roadway> lst = null;
            if (!Common.C_Utils.MyCacheTools.IsCacheExist(rdid))
            {
                lst = this.Scene.Bll.B_Roadway.SearchById<B_Roadway>(rdid);
                Common.C_Utils.MyCacheTools.SetCache(rdid, lst, 24);
            }
            else
            {
                lst = Common.C_Utils.MyCacheTools.GetCache(rdid) as List<B_Roadway>;
            }
            if (lst.Count > 0)
                return lst[0];
            return null;
        }
    }
}